package cc.chinagps.gateway.unit.eg.download;

import cc.chinagps.gateway.buff.CommandBuff;
import cc.chinagps.gateway.buff.CommandBuff.Command;
import cc.chinagps.gateway.exceptions.WrongFormatException;
import cc.chinagps.gateway.log.LogManager;
import cc.chinagps.gateway.seat.cmd.CmdUtil;
import cc.chinagps.gateway.seat.cmd.ServerToUnitCommand;
import cc.chinagps.gateway.stream.OutputPackageEncoder;
import cc.chinagps.gateway.unit.UnitSocketSession;
import cc.chinagps.gateway.unit.common.SegServerToUnitCommand;
import cc.chinagps.gateway.unit.eg.define.EGDefines;
import cc.chinagps.gateway.unit.eg.pkg.EGHead;
import cc.chinagps.gateway.unit.eg.pkg.EGPackage;
import cc.chinagps.gateway.unit.eg.util.EGPkgUtil;
import cc.chinagps.gateway.unit.eg.util.EGTimeFormatUtil;
import org.apache.log4j.Logger;

import java.util.List;

public class EGDownloadCmdEncoder implements OutputPackageEncoder {
    private Logger logger_debug = Logger.getLogger(LogManager.LOGGER_NAME_DEBUG);

    @Override
    public ServerToUnitCommand encode(CommandBuff.Command userCmd, UnitSocketSession unitSession) throws Exception {
        int cmdIdx = userCmd.getCmdId();
        switch (cmdIdx) {
            case CmdUtil.CMD_ID_EGMP_REMOTE_UPGRADE:
            case CmdUtil.CMD_ID_EGMP_SET_VEHICLE_CONF:
                return getRemoteUpgradeCmd(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_COMMON_TEXT:
                return getEgmpCommonTextCmd(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_SET_VIN:
                return getEgmpSetVinCmd(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_SET_IP_PORT:
                return getEgmpSetIpPortCmd(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_CAN_RESET:
                return getCanResetCmd(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_TERMINAL_RESET:
                return getTerminalResetCmd(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_QUERY_TERMINAL_PARAMS:
                return getQueryTerminalParams(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_QUERY_TERMINAL_VERSION:
                return getQueryTerminalVersion(userCmd, unitSession);
            case CmdUtil.CMD_ID_EGMP_INIT_TERMINAL_PARAM:
                return getInitTerminalParamCmd(userCmd, unitSession);
            default:
                throw new WrongFormatException("[EG] no encoder, cmdId:" + cmdIdx);
        }
    }

    private ServerToUnitCommand getInitTerminalParamCmd(Command userCmd, UnitSocketSession unitSession) throws Exception{
        List<String> params = userCmd.getParamsList();
        if (params.size() < 1) {
            throw new WrongFormatException("[EG] not enough params, min: 1, current:" + params.size());
        }
        String value = params.get(0);

        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:0111$ValType:01$Value:");
        content.append(value);
        logger_debug.debug("getInitTerminalParamCmd conent :" + content.toString());
        byte cmdContent[] = content.toString().getBytes(EGDefines.CHARSET);
        byte data[] = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getQueryTerminalVersion(Command userCmd, UnitSocketSession unitSession) throws Exception {
        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:004b$ValType:01$Value:");
        byte[] cmdContent = content.toString().getBytes(EGDefines.CHARSET);
        byte[] data = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getQueryTerminalParams(Command userCmd, UnitSocketSession unitSession) throws Exception {
        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:0064$ValType:01$Value:");
        byte[] cmdContent = content.toString().getBytes(EGDefines.CHARSET);
        byte[] data = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getTerminalResetCmd(Command userCmd, UnitSocketSession unitSession) throws Exception {
        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:0022$ValType:01$Value:");
        byte[] cmdContent = content.toString().getBytes(EGDefines.CHARSET);
        byte[] data = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getCanResetCmd(Command userCmd, UnitSocketSession unitSession) throws Exception {
        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:0077$ValType:01$Value:");
        byte[] cmdContent = content.toString().getBytes(EGDefines.CHARSET);
        byte[] data = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getEgmpSetIpPortCmd(Command userCmd, UnitSocketSession unitSession) throws Exception {
        // TODO Auto-generated method stub
        List<String> params = userCmd.getParamsList();
        if (params.size() < 2) {
            throw new WrongFormatException("[EG] not enough params, min: 2, current:" + params.size());
        }
        String ip = params.get(0);
        String port = params.get(1);

        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:0061$ValType:01$Value:");
        content.append(ip);
        content.append(":");
        content.append(port);
        logger_debug.debug("getEgmpSetIpPortCmd conent :" + content.toString());
        byte cmdContent[] = content.toString().getBytes(EGDefines.CHARSET);
        byte data[] = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getEgmpSetVinCmd(Command userCmd, UnitSocketSession unitSession) throws Exception {
        // TODO Auto-generated method stub
        List<String> params = userCmd.getParamsList();
        if (params.size() < 1) {
            throw new WrongFormatException("[EG] not enough params, min: 1, current:" + params.size());
        }
        String vin = params.get(0);
        if (vin == null || vin.length() != 17) {
            throw new WrongFormatException("[EG] vin len error, current vin:" + vin);
        }

        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:005F$ValType:01$Value:");
        content.append(vin);
        unitSession.getUnitInfo().setVin(vin);
        logger_debug.debug("getEgmpSetVinCmd conent :" + content.toString());
        byte cmdContent[] = content.toString().getBytes(EGDefines.CHARSET);
        byte data[] = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getEgmpCommonTextCmd(Command userCmd, UnitSocketSession unitSession) throws Exception {
        // TODO Auto-generated method stub
        List<String> params = userCmd.getParamsList();
        if (params.size() < 1) {
            throw new WrongFormatException("[EG] not enough params, min: 1, current:" + params.size());
        }
        String text = params.get(0);
//		String textArray[] = text.split("\\$");
//		if (textArray.length != 4) {
//			throw new WrongFormatException("[EG] text format error, current:" + text);
//		}
        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        byte cmdContent[] = text.getBytes(EGDefines.CHARSET);
        byte data[] = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand getRemoteUpgradeCmd(Command userCmd, UnitSocketSession unitSession) throws Exception {
        // TODO Auto-generated method stub
        List<String> params = userCmd.getParamsList();
        if (params.size() < 6) {
            throw new WrongFormatException("[EG] not enough params, min: 6, current:" + params.size());
        }
        String ip = params.get(0);
        String port = params.get(1);
        String userName = params.get(2);
        String pwd = params.get(3);
        String path = params.get(4);
        String fileName = params.get(5);

        byte[] time = EGTimeFormatUtil.getCurrentTime8();
        short serialNo = EGPkgUtil.getSn(unitSession);
        StringBuffer content = new StringBuffer("tsp_para$IdType:0062$ValType:01$Value:");
        content.append("ftp://");
        content.append(userName);
        content.append(":");
        content.append(pwd);
        content.append("&");
        content.append(ip);
        content.append(":");
        content.append(port);
        if (!path.startsWith("/")) {
            content.append("/");
        }
        content.append(path);
        if (!path.endsWith("/")) {
            content.append("/");
        }
        content.append(fileName);
        content.append(";;");
        content.append(userName);
        content.append(";");
        content.append(pwd);
        content.append(";");
        content.append(ip);
        content.append(";");
        content.append(port);
        content.append(";;;;");
        logger_debug.debug("getRemoteUpgradeCmd conent :" + content.toString());
        byte cmdContent[] = content.toString().getBytes(EGDefines.CHARSET);
        byte data[] = new byte[cmdContent.length + 8];
        int pos = 0;
        System.arraycopy(time, 0, data, pos, 6);
        pos += 6;
        System.arraycopy(org.seg.lib.util.Util.getShortByte(serialNo), 0, data, pos, 2);
        pos += 2;
        System.arraycopy(cmdContent, 0, data, pos, cmdContent.length);
        return makeCmd(userCmd, unitSession, (short) 0x81, data, serialNo);
    }

    private ServerToUnitCommand makeCmd(Command userCmd, UnitSocketSession unitSession, short msgId, byte[] body,
                                        short serialNo) throws Exception {
        EGPackage pkg = new EGPackage();
        EGHead head = new EGHead();
        head.setVin(unitSession.getUnitInfo().getVin());
        head.setCmdId((byte) (msgId & 0xFF));
        head.setSoftwareVersion(unitSession.getUnitInfo().getSoftwareVersion());
        head.setEncryption(unitSession.getUnitInfo().getEncryption());
        if (body != null) {
            head.setBodyLen((short) body.length);
        }

        pkg.setHead(head);
        pkg.setData(body);
        byte[] source = pkg.encode();

        SegServerToUnitCommand serverToUnitCommand = new SegServerToUnitCommand();
        serverToUnitCommand.setUserCommand(userCmd);
        String cachedSn = EGPkgUtil.getCmdCacheSn(unitSession.getUnitInfo().getCallLetter(), serialNo);
        serverToUnitCommand.setCachedSn(cachedSn);

        serverToUnitCommand.setData(source);
        serverToUnitCommand.setResponseType(OutputPackageEncoder.SUCCESS_AFTER_RESPONSE);
        return serverToUnitCommand;
    }

}